using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace ShipkaDefenders.Gameplay
{
    public enum EState { Dead, Fight, Walk, Idle, Banner, Banner_Anim }
    public enum SelectionState { None, Banner, Unit, Confirm }
    public class Range
    {
        public Circle Inner { get; set; }
        public Circle Outer { get; set; }
        protected float GetInnerRad()
        {
            return Inner.Radius * g.Scale;
        }
        protected float GetOuterRad()
        {
            return Outer.Radius * g.Scale;
        }
        protected Vector2 GetCenter()
        {
            return Inner.Center;
        }
        protected GameEngine g;
        public Range(GameEngine game, Entity en, float inner, float outer)
        {
            g = game;
            Vector2 p = en.Pos() + new Vector2(en.Rend().Height / 2);
            Inner = new Circle(p, inner);
            Outer = new Circle(p, outer);
        }
        public void Update(Entity en)
        {
            Move(en.Pos() + new Vector2(en.Rend().Height / 2));
        }
        public void Move(Vector2 p)
        {
            Inner = new Circle(p, Inner.Radius);
            Outer = new Circle(p, Outer.Radius);
        }
        protected const int dens = 2;
        public void DrawSelf(AnaLogic g)
        {
            Color tint = Color.Goldenrod;
            Vector2 v = GetCenter() + g.Engine.Scroll;
            float rotation = (float)((g.Elapsed.TotalSeconds) % 3.6) * 100;
            if (!Inner.Radius.Equals(0))
            for (int a = 0; a < (int)(Inner.Radius / dens); a++)
            {
                float angle = Angle(Inner.Radius, a, rotation);
                Vector2 dv = new Vector2((int)Math.Round(GetInnerRad() * Math.Sin(angle)), (int)Math.Round(GetInnerRad() * Math.Cos(angle)));
                Vector2 nv = (v + dv - new Vector2(2));
                g.spriteBatch.Draw(g.MapTextures["range"], new Rectangle((int)nv.X, (int)nv.Y, 3, 3), tint);
            }
            for (int a = 0; a < (int)(Outer.Radius / dens); a++)
            {
                float angle = Angle(Outer.Radius, a, rotation);
                Vector2 dv = new Vector2((int)Math.Round(GetOuterRad() * Math.Sin(angle)), (int)Math.Round(GetOuterRad() * Math.Cos(angle)));
                Vector2 nv = (v + dv - new Vector2(2));
                g.spriteBatch.Draw(g.MapTextures["range"], new Rectangle((int)nv.X, (int)nv.Y, 3, 3), tint);
            }
        }
        private float Angle(float c, int a, float rotation)
        {
            //rotation = 0;
            return ((((float)a / (c / dens)) * 2) * (float)Math.PI) + ((rotation / 360) * (2 * (float)Math.PI));
        }
        public bool Intersects(Entity e) { return Intersects(e.PosFight(), false); }
        public bool Intersects(Entity e, bool j) { return Intersects(e.PosFight(), j); }
        public bool Intersects(Vector2 p, bool j)
        {
            Rectangle r = new Rectangle((int)p.X, (int)p.Y, 1, 1);
            return ((!Inner.Intersects(r) && Outer.Intersects(r)) && (j || Math.Abs(p.Y - Inner.Center.Y) < 20));
        }
    }
    public class Stats
    {
        public Vector2 Health { get; set; }
        public bool FightOnY { get; set; }
        public int MaxFight { get; set; }
        public float Damage { get; set; }
        public double RessurrectionTime { get; set; }
        public bool DoDamage(float d)
        {
            Health -= new Vector2(d, 0);
            return (Health.X <= 0);
        }
        public float GetHealth() { return (Health.X / Health.Y); }
        public Color GetHealthColor()
        {
            float h = GetHealth();
            return (h < 0.75f ? (h < 0.5f ? (h < 0.25f ? Color.Red : Color.Orange) : Color.YellowGreen) : Color.Green);
        }
        public Stats(float health, bool foy, int maxf, float dmg, double res)
        {
            Health = new Vector2(health);
            FightOnY = foy;
            MaxFight = maxf;
            Damage = dmg;
            RessurrectionTime = res;
        }
    }
    public class Entity
    {
        protected AnaLogic g { get; set; }
        public Vector2 Position { get; set; }
        public string TextureGroup { get; set; }
        public EState State { get; set; }
        public TimeSpan StateStart { get; set; }
        public int Cue { get; set; }
        public Vector2 Origin { get; set; }
        public string TextureName { get { return string.Format((TextureGroup.Length > 0 ? "{0}_{1}" : "{1}"), TextureGroup, State.ToString().ToLower()); } }
        protected AnimatedSprite Sprite;
        public Vector3 SpriteInfo;
        public int Index { get; set; }
        public Range Range { get; set; }
        public bool Flip = false;
        public bool UnderAttack = false;
        public Stats Stats;
        public virtual Vector2 Pos() { return g.Engine.Sce(Position) + OriginVect(); }
        public Rectangle Rend()
        {
            int t = (int)(g.MapTextures[TextureName].Height * g.Engine.Scale);
            return new Rectangle((int)Pos().X, (int)Pos().Y, t, t);
        }
        public Texture2D GetTexture() { return g.MapTextures[TextureName]; }
        public Vector2 OriginVect() { return OriginVect(Origin); }
        public Vector2 OriginVect(Vector2 origin)
        {
            Vector2 si = new Vector2(GetTexture().Width, GetTexture().Height);
            if (SpriteInfo != Vector3.Zero && SpriteInfo != null) si = new Vector2(SpriteInfo.X, SpriteInfo.Y);
            return new Vector2(si.X * (origin.X * g.Engine.Scale), si.Y * (origin.Y * g.Engine.Scale));
        }
        public void SetState(EState s)
        {
            if (!State.Equals(s))
            {
                State = s;
                TimeSpan ts = g.Elapsed;
                if (g.Screen.GetType().Name.Equals("GameEngine")) ts = g.Engine.GetTime();
                StateStart = ts;
            }
        }
        public void SetSprite() { SetSprite(TextureName); }
        public void SetSprite(string TextureN)
        {
            if (Sprite == null || Sprite.en.TextureName != TextureN)
                Sprite = new AnimatedSprite(g, this);
        }
        public Vector2 PosFight() { return Pos() + OriginVect(new Vector2(0.5f)); }
        public void DrawHealth()
        {
            bool sel = false;
            if (this.GetType().Name.Equals("Ally")) sel = (this as Ally).Selected;
            if (State == EState.Fight || State == EState.Dead || sel || UnderAttack)
            {
                Vector2 v = (PosFight() - OriginVect(new Vector2(0.5f)) + g.Engine.Scroll);
                Rectangle r = new Rectangle((int)(v.X + ((GetTexture().Height - 50) / 2)), (int)(v.Y + (this.GetType().Name.Equals("Ally") && State.Equals(EState.Dead) ? 45 : 0)), 50, 6);
                Rectangle b = r;
                Rectangle h = r;
                b.Inflate(1, 1);
                h.Width = (int)(r.Width * Stats.GetHealth());
                g.spriteBatch.Draw(g.MapTextures["box"], b, Color.Black);
                g.spriteBatch.Draw(g.MapTextures["box"], r, Color.Black);
                g.spriteBatch.Draw(g.MapTextures["box"], h, Stats.GetHealthColor());
            }
        }
        public virtual SelectionState Tap(Vector2 p) { return SelectionState.None; }
        public virtual void Die() { }
        public virtual void Build(string ClassName) { }
    }
    public class AnimatedSprite
    {
        protected AnaLogic g;
        protected Vector2 t;
        protected int f;
        protected int frames { get { return (int)(t.X / t.Y); } }
        protected int ftime = 66;
        protected double elapsed;
        protected bool lastf;
        public Entity en;
        Vector3 si;
        public AnimatedSprite(AnaLogic game, Entity e)
        {
            g = game;
            en = e;
            t = new Vector2(g.MapTextures[en.TextureName].Width, g.MapTextures[en.TextureName].Height);
            si = new Vector3(en.GetTexture().Height);
            if (en.SpriteInfo != null) si = en.SpriteInfo;
        }
        public void Update(TimeSpan e)
        {
            if (en.TextureName.Contains("russian") || en.TextureName.Contains("turk")) e = g.Engine.UpdateTime(e);
            elapsed += e.Milliseconds;
            if (elapsed > ftime)
            {
                elapsed = 0;
                f = (f + 1) % frames;
            }
        }
        public void Draw(GameEngine ge, Vector2 p) { Draw(ge, p, false); }
        public void Draw(GameEngine ge, Vector2 p, bool flip)
        {
            if (g.Engine.Status.Equals(GameStatus.Paused)) flip = lastf;
            if (en.TextureName.Equals("russian_dead")) p.Y += 10;
            AnaLogic game = ge.GetGameClass();
            p += ge.Scroll;
            Rectangle dest = new Rectangle((int)p.X, (int)p.Y, (int)(si.X * ge.Scale), (int)(si.Y * ge.Scale));
            Rectangle src = new Rectangle((int)(f * si.Z), 0, (int)si.Z, (int)t.Y);
            System.Diagnostics.Debug.WriteLine(en.OriginVect());
            game.spriteBatch.Draw(game.MapTextures[en.TextureName], dest, src, Color.White, 0, Vector2.Zero, (flip ? SpriteEffects.FlipHorizontally : SpriteEffects.None), 0.0f);
            //game.spriteBatch.DrawString(game.MapFonts["Calibri18"], p.ToString(), p, Color.Yellow);
            lastf = flip;
        }
    }
}